/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package database.worker;

import database.DatabaseManager;
import dto.Event;
import dto.ImageEvent;
import dto.Track;
import dto.VideoEvent;
import gui.data.ITrackEventData;
import java.io.File;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutionException;
import javax.swing.DefaultListModel;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

/**
 * Worker to save / update / remove an event on the Database
 * 
 * @author Pascal
 */
public class DBEventWorker extends SwingWorker<Void, Void> {

    public enum Type {
        SaveEvent,
        UpdateEvent,
        RemoveEvent
    }
    
    private Type type;
    private Track track;
    private Event event;
    private IDoneListener doneListener;
    
    /**
     * Creates a new Worker to manipulate or save an event on the db<br/>
     * Use this constructor if the Track is not needed or already known by the event
     * 
     * @param type What type of crap do you want the worker to do?
     * @param event The event to save / update / remove
     */
    public DBEventWorker(Type type, Event event) {
        this(type, event, null);
    }
    
    /**
     * Creates a new Worker to manipulate or save an event on the db
     * 
     * @param type What type of crap do you want the worker to do?
     * @param event The event to save / update / remove
     * @param track the track the event belongs to, may be null if not needed or already known by the event
     * 
     * @throws NullPointerException if type or event is null or track is null and needs to be known
     */
    public DBEventWorker(Type type, Event event, Track track) {
        if (type == null ||
                event == null ||
                (track == null && event.getTrack() == null)) {
            throw new NullPointerException();
        }
        
        this.type = type;
        this.event = event;
        this.doneListener = null;
        
        if (track == null) {
            this.track = event.getTrack();
        }
        else {
            this.track = track;
        }
    }
    /**
     * Set a done listener to get notified when the worker finished successfully.
     * Or set to null, to remove the listener
     * 
     * @param doneListener the listener that wants to get notified
     */
    public void setDoneListener(IDoneListener doneListener) {
        this.doneListener = doneListener;
    }
    
    @Override
    protected Void doInBackground() throws Exception {        
        DatabaseManager db = DatabaseManager.getInstance();
        
        switch (type) {
            case RemoveEvent:
                if (event.getEventType() == ITrackEventData.EventType.Image) {
                    File f = new File(((ImageEvent)event).getImage().getPath());
                    f.delete();
                }
                else if (event.getEventType() == ITrackEventData.EventType.Video) {
                    File f = new File(((VideoEvent)event).getVideo().getPathName());
                    f.delete();
                }
                
                db.removeEvent(event);
                track.getEvents().removeElement(event);
                break;
            case SaveEvent:
                db.saveEvent(event, track);
                
                //insert at correct position
                DefaultListModel<Event> events = track.getEvents();
                int i = 0;
                
                for (i = 0; i < events.size(); i++) {
                    if (event.compareTo(events.get(i)) < 0) {
                        break;
                    }
                }
                
                track.getEvents().add(i, event);
                
                break;
            case UpdateEvent:
                db.updateEvent(event, track);
                
                //see if the changed event need to get repositioned within the list
                DefaultListModel<Event> ev = track.getEvents();
                int j = 0;
                
                for (j = 0; j < ev.size(); j++) {
                    if (event.compareTo(ev.get(j)) <= 0 && !event.equals(ev.get(j))) {
                        break;
                    }
                }
                
                int old = ev.indexOf(event);
                
                if (old != j) {
                    if (old > j) {
                        for (int k = old; k > j; k--) {
                            //swap k and k - 1
                            Event tmp = ev.get(k - 1);
                            ev.set(k - 1, ev.get(k));
                            ev.set(k, tmp);
                        }
                    }
                    else {
                        for (int k = old; k < j - 1; k++) {
                            //swap k and k - 1
                            Event tmp = ev.get(k + 1);
                            ev.set(k + 1, ev.get(k));
                            ev.set(k, tmp);
                        }
                    }
                }
                
                break;
        }
        
        return null;
    }
    
    @Override
    protected void done() {
        try {
            Object ret = get();
            
            if (doneListener != null) {
                doneListener.done(ret);
            }
        } catch (InterruptedException ex) {
        } catch (ExecutionException ex) {
            JOptionPane.showMessageDialog(null,
                    ResourceBundle.getBundle("gui/guilabels").getString("errorexecution") + ex.getLocalizedMessage(),
                    ResourceBundle.getBundle("gui/guilabels").getString("error"),
                    JOptionPane.ERROR_MESSAGE);
        }
    }
}
